package com.zjb.service.impl;

import com.zjb.service.PasswordCrackService;
import com.zjb.utils.ExcelUtil;
import com.zjb.utils.StringUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
 * 破解服务实现类
 */
public class ThreadProcessPasswordCrackServiceImpl implements PasswordCrackService {

    private static volatile boolean runResult = false;

    /**
     * 加密的excel
     */
    private String filePath;
    /**
     * 文件类型
     */
    private String fileType;
    /**
     * 破解成功后保存密码的文件
     */
    private String savePasswdFilePath;
    private ThreadPoolExecutor threadPoolExecutor;

    public ThreadProcessPasswordCrackServiceImpl(String filePath, String fileType, String savePasswdFilePath) {
        this.threadPoolExecutor = new ThreadPoolExecutor(4, 20, 60,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        this.filePath = filePath;
        this.fileType = fileType;
        this.savePasswdFilePath = savePasswdFilePath;
    }
 
    @Override
    public Boolean run(Integer passwdLength) {
        System.out.println("开始破解，密码位数：" + passwdLength);
        List<String> numberStr = StringUtil.getNumberStr(passwdLength);
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
        numberStr.forEach(num -> queue.offer(num));
        while (!runResult && !queue.isEmpty()) {
            threadPoolExecutor.execute(() -> {
                String name = Thread.currentThread().getName();
                String key = queue.poll();
                if (Objects.nonNull(key) && key.length() > 0) {
                    boolean result = ExcelUtil.getExcelPassword(filePath, fileType, key);
                    if (result) {
                        System.out.println("破解成功,密码是：" + key);
                        try(FileOutputStream out = new FileOutputStream(savePasswdFilePath)) {
                            out.write(key.getBytes(StandardCharsets.UTF_8));
                            out.flush();
                            runResult = true;
                        } catch (Exception e) {
                            System.out.println("文件无法打开，密码保存失败！！！");
                        }
                        queue.clear();
                    } else {
                        System.out.println("线程：" + name + "," + key + "密码错误");
                    }
                }
            });
        }
        return runResult;
    }
}